package cn.sciento.iam.saas.domain.service.observer;

import javax.annotation.Nonnull;
import org.apache.commons.lang3.StringUtils;
import cn.sciento.iam.domain.entity.PasswordPolicy;
import cn.sciento.iam.domain.entity.Tenant;
import cn.sciento.iam.domain.repository.PasswordPolicyRepository;
import cn.sciento.iam.saas.domain.service.TenantObserver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.Assert;

public class TenantPasswordPolicyObserver implements TenantObserver<PasswordPolicy> {
  private static final Logger LOGGER = LoggerFactory.getLogger(TenantPasswordPolicyObserver.class);
  
  @Value("${stong.password-policy.default.max-error-time:5}")
  private Integer maxErrorTime;
  
  @Value("${stong.password-policy.default.lock-expire-time:86400}")
  private Integer lockedExpireTime;
  
  @Value("${stong.password-policy.default.max-check-captcha:3}")
  private Integer maxCheckCaptcha;
  
  @Value("${stong.password-policy.default.original-password:123456}")
  private String originalPassword;
  
  @Autowired
  private PasswordPolicyRepository passwordPolicyRepository;
  
  @Override
  public int order() {
    return 30;
  }
  
  @Override
  public PasswordPolicy tenantCreate(@Nonnull Tenant tenant) {
    PasswordPolicy passwordPolicy = generateDefaultPasswordPolicy(tenant);
    this.passwordPolicyRepository.insertSelective(passwordPolicy);
    PasswordPolicy dbPasswordPolicy = this.passwordPolicyRepository.selectTenantPasswordPolicy(tenant.getTenantId());
    this.passwordPolicyRepository.cachePasswordPolicy(dbPasswordPolicy);
    LOGGER.info("[TenantInit - Num={}] -> {}", tenant.getTenantNum(), passwordPolicy);
    return passwordPolicy;
  }
  
  @Override
  public PasswordPolicy tenantUpdate(@Nonnull Tenant tenant) {
    PasswordPolicy passwordPolicy = this.passwordPolicyRepository.selectTenantPasswordPolicy(tenant.getTenantId());
    Assert.notNull(passwordPolicy, "error.data_not_exists");
    if (!StringUtils.equals(tenant.getTenantName(), passwordPolicy.getName())) {
      passwordPolicy.setName(tenant.getTenantName());
      this.passwordPolicyRepository.updateOptional(passwordPolicy, "name");
      this.passwordPolicyRepository.cachePasswordPolicy(passwordPolicy);
      LOGGER.info("Update tenant passwordPolicy, tenantNum is [{}], passwordPolicy is {}", tenant, passwordPolicy);
    } 
    return passwordPolicy;
  }
  
  protected PasswordPolicy generateDefaultPasswordPolicy(Tenant tenant) {
    PasswordPolicy passwordPolicy = new PasswordPolicy();
    passwordPolicy.setOrganizationId(tenant.getTenantId());
    passwordPolicy.setOriginalPassword(this.originalPassword);
    passwordPolicy.setCode(tenant.getTenantNum());
    passwordPolicy.setName(tenant.getTenantName());
    passwordPolicy.setMaxCheckCaptcha(this.maxCheckCaptcha);
    passwordPolicy.setMaxErrorTime(this.maxErrorTime);
    passwordPolicy.setLockedExpireTime(this.lockedExpireTime);
    passwordPolicy.setEnableSecurity(Boolean.TRUE);
    passwordPolicy.setEnableCaptcha(Boolean.TRUE);
    passwordPolicy.setEnableLock(Boolean.TRUE);
    passwordPolicy.setMaxLength(30);
    passwordPolicy.setMinLength(6);
    passwordPolicy.setDigitsCount(0);
    passwordPolicy.setLowercaseCount(0);
    passwordPolicy.setUppercaseCount(0);
    passwordPolicy.setSpecialCharCount(0);
    return passwordPolicy;
  }
}
